#include <dspSimulator/command/watchMemory.h>
#include <dspSimulator/dspSimulator/dspSimulator.h>

void WatchMemoryCommand::execute(std::string command) {
    auto dspSimulator = dynamic_cast<DSPSimulator *>(m_simulator);
    if (dspSimulator == nullptr) {
        fatalMacro("该模拟器对象不为dsp模拟器对象!");
    }
    auto targetMachine = dspSimulator->m_targetMachine;
    auto dspMachine = std::dynamic_pointer_cast<DspMachine>(targetMachine);
    if (dspMachine == nullptr) {
        fatalMacro("该目标机对象不为dsp目标机对象!");
    }

    if (command.size() < 3) {
        requestReEnter;
        return;
    }
    u32 address = std::stoul(command.substr(2), nullptr, 16);
    auto index = command.find('/');
    if (index == std::string::npos || index == command.size() - 1) {
        requestReEnter;
        return;
    }
    u32 num = stoul(command.substr(index + 1));
    auto dataStr = readMemDataAndToString(address, num);
    fprintf(stdout, "%08X\t%s\n", address, dataStr.c_str());
}

std::string WatchMemoryCommand::readMemDataAndToString(u32 address, u32 byteNum) {
    if (byteNum == 0)
        return {};

    auto dspSimulator = dynamic_cast<DSPSimulator *>(m_simulator);
    if (dspSimulator == nullptr) {
        fatalMacro("该模拟器对象不为dsp模拟器对象!");
    }
    auto targetMachine = dspSimulator->m_targetMachine;
    auto dspMachine = std::dynamic_pointer_cast<DspMachine>(targetMachine);
    if (dspMachine == nullptr) {
        fatalMacro("该目标机对象不为dsp目标机对象!");
    }

    std::string res;
    auto memory = dspMachine->getMMU()->getMemory();
    auto data = memory->readNBytes(address, byteNum);
    for (u32 i = 0; i < byteNum; ++i) {
        res += dec2hex(static_cast<u32>(data[i])) + " ";
    }
    return res;
}

std::shared_ptr<WatchMemoryCommand> WatchMemoryCommand::get(Simulator* dspSimulator) {
    static std::shared_ptr<WatchMemoryCommand> watchMemoryCommand;
    if (watchMemoryCommand == nullptr) {
        watchMemoryCommand = std::make_shared<WatchMemoryCommand>(dspSimulator);
    }
    return watchMemoryCommand;
}
